#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>
#include "thread_pool.hpp"
#include "task.hpp"

using namespace std;
using namespace ns_tp;
using namespace ns_task;

void ServerRun(int nfd)
{
#define NUM 1024
    while (1)
    {
        char buf[NUM] = {0};
        ssize_t sz = read(nfd, buf, NUM - 1);
        if (sz > 0)
        {
            std::cout << "client# " << buf << std::endl;

            std::string s;

            s += ">>server<< ";
            s += buf;

            write(nfd, s.c_str(), s.size());
        }
        else if (sz == 0)
        {
            cout << "对端关闭" << endl;
            return;
        }
        else
        {
            return;
        }
    }
}

void* Rountine(void* args)
{
    pthread_detach(pthread_self());
    int sock = *(int*)args;
    
    ServerRun(sock);
    close(sock);
}

void Usage()
{
    cout << "Usage: "
         << "./server port" << endl;
}

int main(int argc, char *argv[])
{
    // signal(SIGCHLD, SIG_IGN);
    thread_pool<task>* tp = new thread_pool<task>();
    tp->init();
    if (argc != 2)
    {
        Usage();
        return 1;
    }

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        return 2;
    }

    uint16_t port = atoi(argv[1]);

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock, (sockaddr *)&local, sizeof(local)) < 0)
    {
        return 3;
    }

    if (listen(sock, 5) < 0)
    {
        return 4;
    }

    while (1)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int nfd = accept(sock, (sockaddr *)&peer, &len);
        if (nfd < 0)
            continue;
        // if (fork() == 0)
        // {
        //     close(sock);
        //     ServerRun(nfd);
        //     exit(0);
        // }
        // close(nfd);
        // pthread_t tid;
        // pthread_create(&tid, nullptr, Rountine, (void*)&nfd);
        task t(nfd);
        tp->push(t);
        
    }
    return 0;
}